//
//  Home.swift
//  home
//
//  Created by Yun Zeng on 2018/11/25.
//  Copyright © 2018 Yun Zeng. All rights reserved.
//

import Foundation

enum HomeMessagePath: String {
    case home = "home"
    case homeInfo = "home/info"
    case container = "home/container"
    case containerCharacteristic = "home/container/characteristic"
    case characteristic = "home/characteristic"
    case characteristicLog = "home/characteristic/log"
    case scene = "home/scene"
}

class Home: Codable {
    var id: String
    var name: String
    var version: Int = 0
    
    var containerManager: HomeContainerManager!
    var serviceManager: ServiceManager!
    var memberManager: HomeMemberManager!
    var sceneManager: HomeSceneManager!
    var roomManager: RoomManager!
    var automationManager: HomeAutomationManager!


    private enum CodingKeys: String, CodingKey {
        case id
        case name
        case version
        case containerManager = "containers"
        case serviceManager = "services"
        case memberManager = "members"
        case sceneManager = "scenes"
        case roomManager = "rooms"
        case automationManager = "automations"
    }
    
    init(id: String, name: String) {
        self.id = id
        self.name = name
        self.containerManager = HomeContainerManager(containers: [])
        self.containerManager.home = self
        self.serviceManager = ServiceManager(services: [])
        self.roomManager = RoomManager(rooms: [])
        self.automationManager = HomeAutomationManager(automations: [])
    }
    
    
    init?(data: Data) {
        guard let home = try? JSONDecoder().decode(Home.self, from: data) else {
            return nil
        }
        self.id = home.id
        self.name = home.name
        self.version = home.version
        
        // 家庭房间
        if home.roomManager == nil {
            self.roomManager = RoomManager(rooms: [])
        } else {
            self.roomManager = home.roomManager
        }
        
        // 容器
        if home.containerManager == nil {
            self.containerManager = HomeContainerManager(containers: [])
        } else {
            self.containerManager = home.containerManager
        }
        self.containerManager!.home = home
        
        // 设备
        if home.serviceManager == nil {
            self.serviceManager = ServiceManager(services: [])
        } else {
            self.serviceManager = home.serviceManager
        }
        self.serviceManager.linkHome(home: home)
        
        // 家庭场景
        if home.sceneManager == nil {
            self.sceneManager = HomeSceneManager(scenes: [], home: home)
        } else {
            self.sceneManager = home.sceneManager
            self.sceneManager.home = home
        }
        
        // 家庭自动化
        if home.automationManager == nil {
            self.automationManager = HomeAutomationManager(automations: [])
        } else {
            self.automationManager = home.automationManager
        }
        
        // 家庭成员
        if home.memberManager == nil {
            self.memberManager = HomeMemberManager(members: [])
        } else {
            self.memberManager = home.memberManager
        }
    }
    
    
    // 家庭数据同步
    func sync() {
        var msg = CloudMessage(path: HomeMessagePath.homeInfo.rawValue, method: .get, data: nil)
        msg.home = self.id
        CloudClient.instance.sendMessage(msg: msg)
        
        msg = CloudMessage(path: HomeMessagePath.containerCharacteristic.rawValue, method: .get, data: nil)
        msg.home = self.id
        CloudClient.instance.sendMessage(msg: msg)
    }
    
    // 需要更新家庭数据
    // isContainer: 是否为容器数据更新因此的家庭数据变化
    func needUpdate(isContainer: Bool = false) {
        if isContainer {
            self.serviceManager.linkHome(home: self, update: false)
        }
        self.version += 1
        _ = self.save()
    }
    
    // 处理家庭消息
    func handleMsg(msg: CloudMessage) -> CloudMessageError {
        guard let data = msg.data else {
            return .invalidParameter
        }
        
        // 家庭信息获取
        if msg.path == HomeMessagePath.homeInfo.rawValue {
            guard let home = try? JSONDecoder().decode(Home.self, from: data) else {
                return .jsonFormatError
            }
            
            if home.version == self.version {
                return .success
            }
                
            // 服务器版本大于本地版本
            else if home.version > self.version {
                let getMsg = CloudMessage(path: HomeMessagePath.home.rawValue, method: .get, data: nil)
                getMsg.home = self.id
                CloudClient.instance.sendMessage(msg: getMsg)
                _ = self.save()
            }
            
            // 服务器版本小于本地版本
            else if home.version < self.version {
                let postMsg = CloudMessage(path: HomeMessagePath.home.rawValue, method: .post, object: self)
                postMsg.home = self.id
                CloudClient.instance.sendMessage(msg: postMsg)
            }
        }
        return .success
    }
}

// 家庭消息处理
extension Home: CloudMessageHandler {
    func handle(msg: CloudMessage) -> CloudMessageError {
        switch msg.path {
        case _ where msg.path.hasPrefix(HomeMessagePath.container.rawValue):
            if let result = self.containerManager?.handle(msg: msg) {
                if result == .success {
                    self.serviceManager.refresh()
                }
                return result
            }
            return .invalidParameter
            
        case HomeMessagePath.characteristic.rawValue:
            if let result = self.containerManager?.handle(msg: msg) {
                if result == .success {
                    self.serviceManager.refresh()
                }
                return result
            }
            return .invalidParameter
            
        case HomeMessagePath.homeInfo.rawValue,
             HomeMessagePath.home.rawValue:
            return self.handleMsg(msg: msg)
            
        default:
            return .invalidParameter
        }
    }
    
    func clientStateChange(state: CloudClient.State) {
    }
}

// 家庭配置文件的保存
extension Home {
    func save() -> Bool {
        let file = Storage.Path.appendingPathComponent("home[\(self.id)]").appendingPathExtension("json")
        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        if let data = try? encoder.encode(self), ((try? data.write(to: file)) != nil) {
            Logger.Info("home save: \n\(String(data: data, encoding: .utf8)!)")
            return true
        }
        return false
    }
    
    static func new(id: String) -> Home {
        let file = Storage.Path.appendingPathComponent("home[\(id)]").appendingPathExtension("json")
        Logger.Info("path: \(file)")
        if let data = try? Data(contentsOf: file) {
            if let home =  Home(data: data) {
                return home
            }
        }
        return Home(id: id, name: "我的家")
    }
}


// 调试打印输出
extension Home: CustomStringConvertible {
    var description: String {
        let encoder = JSONEncoder()
        encoder.outputFormatting = .prettyPrinted
        let data = try! encoder.encode(self)
        return String(data: data, encoding: .utf8)!
    }
}

